package com.yhao.stock.common.service;

import com.gargoylesoftware.htmlunit.*;
import com.yhao.stock.common.listener.MyJSErrorListener;
import com.yhao.stock.common.utils.DateUtil;
import com.yhao.stock.entity.FinanceInfo;
import com.yhao.stock.service.FinanceInfoService;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * @author : yhao
 * @Date : 2023/11/30 - 11:48
 * @Desc : 雪球服务  雪球不让爬
 */
@Service
@Slf4j
public class XQService {

    WebClient webClient = null;

    //初始化
    public XQService() {
        webClient = new WebClient(BrowserVersion.CHROME);//新建一个模拟谷歌Chrome浏览器的浏览器客户端对象
        webClient.getOptions().setThrowExceptionOnScriptError(false);//当JS执行出错的时候是否抛出异常, 这里选择不需要
        webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);//当HTTP的状态非200时是否抛出异常, 这里选择不需要
        webClient.getOptions().setActiveXNative(false);
        webClient.getOptions().setCssEnabled(false);//是否启用CSS, 因为不需要展现页面, 所以不需要启用
        webClient.getOptions().setJavaScriptEnabled(true); //很重要，启用JS。有些网站要开启！
        webClient.setAjaxController(new NicelyResynchronizingAjaxController());//很重要，设置支持AJAX
        webClient.getOptions().setTimeout(30000);
        webClient.setJavaScriptErrorListener(new MyJSErrorListener());
        webClient.setJavaScriptTimeout(10000);
    }

    //获取某个url的web客户端
    public String htmlUnitUrl(String url, WebClient webClient) {

        try {
            WebRequest request = new WebRequest(new URL(url), HttpMethod.GET);
            Map<String, String> additionalHeaders = new HashMap<String, String>();


            request.setAdditionalHeaders(additionalHeaders);
            // 获取某网站页面
            Page page = webClient.getPage(request);
            return page.getWebResponse().getContentAsString();
        } catch (Exception e) {
            log.error(e.getLocalizedMessage());
        } finally {
            webClient.close();
        }
        return null;
    }

    /**
     * @param dCode
     * @param dName
     * @return
     * @desc 获取股票的财务信息
     */
    public boolean getFinanceInfo(String dCode, String dName) {
        String url = "";
        if (dCode.startsWith("60")) {
            url = "https://xueqiu.com/S/SH" + dCode;
        } else {
            url = "https://xueqiu.com/S/SZ" + dCode;
        }

        log.info("getFinanceInfo   url=" + url);
        String content = htmlUnitUrl(url, webClient);
        return saxFinanceInfo(dCode, dName, content);
//        return false;
    }

    @Autowired
    private FinanceInfoService financeInfoService;

    private boolean saxFinanceInfo(String dCode, String dName, String content) {
        if (content == null) {
            log.info("dCode[" + dCode + "],dName=[" + dName + "],content=为null");
            return false;
        }
        Document document = Jsoup.parse(content);
        val elementsTable = document.getElementsByClass("quote-info");

        val elementTr2 = elementsTable.get(0).getElementsByTag("tr").get(2);
        Elements tdElements = elementTr2.getElementsByTag("td");
        String peDStr = tdElements.get(2).getElementsByTag("span").get(0).text();
        if (peDStr.equals("--") || peDStr.equals("-") || peDStr.equals("亏损")) {
            peDStr = "-1";
        }
        String peTTMStr = tdElements.get(3).getElementsByTag("span").get(0).text();
        if (peTTMStr.equals("--") || peTTMStr.equals("-") || peTTMStr.equals("亏损")) {
            peTTMStr = "-1";
        }

        val elementTr3 = elementsTable.get(0).getElementsByTag("tr").get(3);
        tdElements = elementTr3.getElementsByTag("td");
        String peJStr = tdElements.get(2).getElementsByTag("span").get(0).text();
        if (peJStr.equals("--") || peJStr.equals("-") || peJStr.equals("亏损")) {
            peJStr = "-1";
        }

        String pbrStr = tdElements.get(3).getElementsByTag("span").get(0).text();
        if (pbrStr.equals("--") || pbrStr.equals("-") || pbrStr.equals("亏损")) {
            pbrStr = "-1";
        }

        val elementTr4 = elementsTable.get(0).getElementsByTag("tr").get(4);
        tdElements = elementTr4.getElementsByTag("td");
        String piStr = tdElements.get(0).getElementsByTag("span").get(0).text();
        if (piStr.equals("--") || piStr.equals("-") || piStr.equals("亏损")) {
            piStr = "-1";
        }

        String ttmStr = tdElements.get(1).getElementsByTag("span").get(0).text();
        if (ttmStr.equals("--") || ttmStr.equals("-") || ttmStr.equals("亏损")) {
            ttmStr = "-1";
        }

        BigDecimal totalEquity = null;
        String teStr = tdElements.get(2).getElementsByTag("span").get(0).text();
        if (teStr.contains("万亿")) {
            totalEquity = new BigDecimal(teStr.replace("万亿", "")).multiply(new BigDecimal(10000));
        } else {
            totalEquity = new BigDecimal(teStr.replace("亿", ""));
        }

        BigDecimal totalMarketValue = null;
        String tmvStr = tdElements.get(3).getElementsByTag("span").get(0).text();
        if (tmvStr.contains("万亿")) {
            totalMarketValue = new BigDecimal(tmvStr.replace("万亿", "")).multiply(new BigDecimal(10000));
        } else {
            totalMarketValue = new BigDecimal(tmvStr.replace("亿", ""));
        }

        val elementTr5 = elementsTable.get(0).getElementsByTag("tr").get(5);
        tdElements = elementTr5.getElementsByTag("td");

        String paStr = tdElements.get(0).getElementsByTag("span").get(0).text();
        if (paStr.equals("--") || paStr.equals("-") || paStr.equals("亏损")) {
            paStr = "-1";
        }

        String ttmRStr = tdElements.get(1).getElementsByTag("span").get(0).text();
        if (ttmRStr.equals("--") || ttmRStr.equals("-") || ttmRStr.equals("亏损")) {
            ttmRStr = "-1";
        }

        BigDecimal circulateStock = null;
        String csStr = tdElements.get(2).getElementsByTag("span").get(0).text();
        if (csStr.endsWith("万亿")) {
            circulateStock = new BigDecimal(csStr.replace("万亿", "")).multiply(new BigDecimal(10000));
        } else if (csStr.endsWith("亿")) {
            circulateStock = new BigDecimal(csStr.replace("亿", ""));
        } else if (csStr.endsWith("万")) {
            circulateStock = new BigDecimal(csStr.replace("万", "")).divide(new BigDecimal(10000), 6, RoundingMode.HALF_UP);
        }

        BigDecimal circulateValue = null;
        String cvStr = tdElements.get(3).getElementsByTag("span").get(0).text();
        if (cvStr.endsWith("万亿")) {
            circulateValue = new BigDecimal(cvStr.replace("万亿", "")).multiply(new BigDecimal(10000));
        } else if (cvStr.endsWith("亿")) {
            circulateValue = new BigDecimal(cvStr.replace("亿", ""));
        } else if (cvStr.endsWith("万")) {
            circulateValue = new BigDecimal(cvStr.replace("万", "")).divide(new BigDecimal(10000), 6, RoundingMode.HALF_UP);
        }

        val elementTr6 = elementsTable.get(0).getElementsByTag("tr").get(6);
        tdElements = elementTr6.getElementsByTag("td");
        String yhStr = tdElements.get(0).getElementsByTag("span").get(0).text();
        String ylStr = tdElements.get(1).getElementsByTag("span").get(0).text();
        String registerStr = tdElements.get(2).getElementsByTag("span").get(0).text();
        Integer register = 0;
        if (registerStr.equals("是")) {
            register = 1;
        }
        FinanceInfo financeInfo = new FinanceInfo(dCode, dName,
                new BigDecimal(peDStr),
                new BigDecimal(peJStr),
                new BigDecimal(peTTMStr),
                new BigDecimal(pbrStr),
                new BigDecimal(piStr),
                new BigDecimal(ttmStr),
                totalEquity,
                totalMarketValue,
                new BigDecimal(paStr),
                new BigDecimal(ttmRStr.replace("%", "")),
                circulateStock,
                circulateValue,
                new BigDecimal(yhStr),
                new BigDecimal(ylStr),
                register,
                DateUtil.getSimpleDate(), LocalDateTime.now());
        log.info("code ==[" + dCode + "] 保存成功");
        return financeInfoService.save(financeInfo);
    }
}
